CNC-Beispiel 10: Dynamische CNC-Bahn programmieren
Sehen Sie hierzu das Beispielprojekt CNC10_DynamicPath.project
im Installationsverzeichnis von CODESYS unter ..\CODESYS SoftMotion\Examples
.
In diesem Beispiel wird gezeigt, wie eine CNC-Bahn direkt in der Applikation zur Laufzeit erzeugt werden kann, also nicht aus einem CNC-Programmobjekt oder einer Datei mit G-Code gespeist wird. Wenn ein solches herkömmliches CNC-Programm übersetzt wird, werden die Bahndaten in einer Datenstruktur mit Datentyp SMC_CNC_Data
gespeichert. Diese internen Daten werden dann abhängig vom Übersetzungsmodus (SMC_CNC_REF oder SMC_OutQueue) in spezielle globale Datenstrukturen übersetzt.
Beim Übersetzungsmodus SMC_CNC_REF werden die Daten in einem Array von Elementen des Typs SMC_GEOINFO
gespeichert. Üblicherweise wird das Array im Applikationscode an die Funktionsbaustein-Instanz SMC_NCDecoder
übergeben. Zur Laufzeit werden die Daten dort decodiert und in eine globale Datenstruktur des Typs SMC_OUTQUEUE
ablegt. Anschließend können Bahnvorverarbeitungsbausteine aufgerufen werden.
Beim Übersetzungsmodus SMC_OutQueue wird direkt eine globale Datenstruktur (SMC_OUTQUEUE
) erzeugt, die im Applikationscode an den Interpolator (FB-Instanz SMC_Interpolator
) übergeben wird. Der Funktionsbaustein SMC_NCDecoder
wird nicht aufgerufen.
Beim Übersetzungsmodus FILE werden die Daten in einer Datei gespeichert. Die Daten sind dabei als Array von Elementen des Typs SMC_GEOINFO
abgelegt und entsprechen den Daten, die beim Übersetzungsmodus SMC_CNC_REF erzeugt werden.
Statt die CNC-Bahn grafisch zu programmieren, können Sie einen Applikationscode programmieren, der zur Laufzeit eine Datenstruktur des Typs SMC_OUTQUEUE
instanziert und ihr Werte zuweist. Sie programmieren eine CNC-Bahn, die zur Laufzeit dynamisch erzeugt wird. Die Datenstruktur können Sie dann an weitere Funktionsbaustein-Instanzen (beispielsweise an Bahnvorverarbeitungsbausteine oder an den Funktionsbaustein SMC_Interpolator
) übergeben.
Programmieren
Tipp
Im Installationsverzeichnis von CODESYS finden Sie das Beispielprojekt CNCDynamicPath
. Das Beispielprojekt wurde aus dem Projekt CNConline
entwickelt. Es enthält statt der grafisch programmierten Bahn Example
das Programm Path
. Es erzeugt dynamisch eine Datenstruktur mit Typ SMC_OUTQUEUE
.
Deklarieren Sie eine Datenstruktur des Typs
SMC_OUTQUEUE
. Die Datenstruktur enthält die CNC-Bahndaten und wird dynamisch gefüllt.Beispiel:
QUEUE
Allozieren Sie Speicher für die Bahn mit der gewünschten Anzahl an
SMC_GEOINFO
-Elementen.Beispiel:
BUF
Deklarieren Sie eine Variable des Typs
SMC_GEOINFO
mit einem Initialschritt.Beispiel:
GEO
Ein Arrayelement des Datenyps
SMC_GEOINFO
entspricht einem Bahnelement im CNC-Code. Für jedes Element müssen folgende Schritte durchgeführt werden, um es derSMC_OUTQUEUE
hinzuzufügen:Jedes Arrayelement verfügt über eine Startposition, die der Endposition des vorhergehenden Arrayelements entspricht.
Beispiel:
GEO.piStartPos.dX := 0;
oderGEO.piStartPos := GEO.piDestPos;
Bestimmen Sie für jedes Arrayelement einen Bewegungstyp.
Beispiel:
GEO.iMoveType := CCLW;
oderGEO.iMoveType := LIN;
Setzen Sie die Parameter des Bewegungstypen. Das ist nicht bei allen Bewegungstypen erforderlich.
Beispiel: Bei einem Kreisbogen (Bewegungstyp CCLW) ist das Setzen der folgenden Positionen erforderlich:
geoinfo_A[i].dP1 := 200; geoinfo_A[i].dP2 := 100; geoinfo_A[i].dP3 := 50; geoinfo_A[i].dT1 := 0; geoinfo_A[i].dT2 := 90;
Fügen Sie die Berechnung der Endposition ein.
SMC_CalcEndPnt(ADR(GEO));
Fügen Sie die Berechnung der Länge des Objekts ein.
SMC_CalcLengthGeo(ADR(GEO));
Speichern Sie das Objekt in
QUEUE
:SMC_AppendObj(POQ:=ADR(QUEUE), PGI:=ADR(GEO));
Wenn die Bahn vollständig erstellt ist, muss die Endmarke gesetzt werden: QUEUE.bEndOfList := TRUE;
Tipp
Wenn anschließend ein Bahnvorverarbeitungsbaustein aufgerufen wird, ist es erforderlich das Anfangs- oder Endbit für InternMark
zu setzen.
CNC-Bahn mit 2 Bahnelementen
In diesem Beispiel sind die Arrays mit den x/y-Positionen nicht definiert. Wenn das wie beschrieben ein Beispiel mit zwei Bahnelementen sein soll, müssten diese Arrays je zwei Elemente haben.
Aus dem Beispielprojekt entlehnt also z. B.:
xp:ARRAY[1..2] OF REAL:= [100,50]; yp:ARRAY[1..2] OF REAL:= [0,100];
PROGRAM Path VAR iState : INT; QUEUE : SMC_OUTQUEUE; BUF : ARRAY[0..49] OF SMC_GEOINFO; // Memory allocation GEO : SMC_GEOINFO:=(dT1:=0, dT2:=1, dToolRadius:=0, dVel:=100, dVel_End:=100, dAccel:=200, dDecel:=500, iObj_Nr:=0); // Initial path element n : INT := 0; QUEUE.nSize := SIZEOF(BUF); END_VAR CASE iState OF 0: QUEUE.pbyBuffer := ADR(BUF[0]); // Initialize QUEUE SMC_SetQueueCapacity(ADR(QUEUE), SIZEOF(BUF)); iState := iState + 1; 1: // Fill QUEUE WHILE NOT QUEUE.bFull DO // When QUEUE is full, wait until it has been processed by the following FBs n := n + 1; GEO.iSourceLine_No := n; GEO.piStartPos := GEO.piDestPos; // Copying last destination GEO.iMoveType := LIN; // Generating linear movement GEO.iObjNo := GEO.iObjNo + 1; // Calculating number GEO.piDestPos.dX := xp[n]; // Generatint position GEO.piDestPos.dY := yp[n]; SMC_CalcLengthGeo(pg := ADR(GEO)); // Calculating length of object with the help of the standard function SMC_AppendObj(poq:=ADR(QUEUE), pgi:=ADR(GEO)); // Appending object to QUEUE IF n = SIZEOF(xp)/SIZEOF(xp[1]) THEN // All target positions processed QUEUE.bEndOfList := TRUE; n := 0; iState := 2; EXIT; END_IF END_WHILE 2: //Done ; END_CASE CheckVel(bExecute:=TRUE , poqDataIn:=ADR(queue)); // Preprocessing
Wichtig
Wenn die Datenstruktur SMC_OUTQUEUE
mit SMC_GEOINFO
-Daten gefüllt und das Datenstrukturelement bFULL = TRUE
gesetzt wurde, dann ist ein weiteres Zuweisen von SMC_GEOINFO
-Daten nicht ratsam. Denn in diesem Fall wird zur Laufzeit die Erstellung der Bahn unterbrochen, bis das erste Element der SMC_OUTQUEUE
-Datenstruktur im Interpolator verarbeitet ist. Erst dann wird ein weiteres Element angehängt.
Vermeiden Sie diese Unterbrechung, indem Sie ausreichend großen Speicher allozieren. Siehe Variable BUF
.
Wichtig
Wenn die Datenstruktur SMC_OUTQUEUE
nach der ersten Ausführung wieder aufgefüllt wird, müssen der Interpolator und alle vorverarbeitenden Funktionsbausteine (beispielsweise SMC_CheckVelocities
) durch eine steigende Flanke an Execute
neu gestartet werden.